// Advanced relationship detection with confidence scoring
use crate::{
    CodeNode, CodeEdge, EdgeType, NodeType, NodeId, Result,
    SourceLocation, EdgeMetadata,
};
use serde::{Serialize, Deserialize};
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use tokio::sync::RwLock;

/// Confidence score for detected relationships (0.0 to 1.0)
pub type ConfidenceScore = f64;

/// Relationship detection configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelationshipConfig {
    /// Minimum confidence threshold for relationships
    pub min_confidence: ConfidenceScore,
    /// Enable semantic analysis
    pub enable_semantic_analysis: bool,
    /// Enable cross-language relationship detection
    pub enable_cross_language: bool,
    /// Maximum depth for transitive relationship detection
    pub max_transitive_depth: usize,
    /// Enable machine learning-based detection
    pub enable_ml_detection: bool,
    /// Weights for different relationship types
    pub relationship_weights: HashMap<EdgeType, f64>,
}

impl Default for RelationshipConfig {
    fn default() -> Self {
        let mut weights = HashMap::new();
        weights.insert(EdgeType::Calls, 1.0);
        weights.insert(EdgeType::References, 0.8);
        weights.insert(EdgeType::Inherits, 0.9);
        weights.insert(EdgeType::Implements, 0.9);
        weights.insert(EdgeType::Contains, 0.7);
        weights.insert(EdgeType::DependsOn, 0.6);

        Self {
            min_confidence: 0.5,
            enable_semantic_analysis: true,
            enable_cross_language: false,
            max_transitive_depth: 3,
            enable_ml_detection: false,
            relationship_weights: weights,
        }
    }
}

/// Detected relationship with confidence score
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DetectedRelationship {
    /// Source node ID
    pub source: NodeId,
    /// Target node ID
    pub target: NodeId,
    /// Type of relationship
    pub edge_type: EdgeType,
    /// Confidence score (0.0 to 1.0)
    pub confidence: ConfidenceScore,
    /// Evidence supporting this relationship
    pub evidence: Vec<RelationshipEvidence>,
    /// Additional metadata
    pub metadata: EdgeMetadata,
    /// Source location where relationship was detected
    pub location: Option<SourceLocation>,
}

/// Evidence supporting a detected relationship
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelationshipEvidence {
    /// Type of evidence
    pub evidence_type: EvidenceType,
    /// Description of the evidence
    pub description: String,
    /// Confidence contribution (0.0 to 1.0)
    pub confidence_contribution: f64,
    /// Source location of the evidence
    pub location: Option<SourceLocation>,
    /// Additional context
    pub context: HashMap<String, String>,
}

/// Types of evidence for relationship detection
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum EvidenceType {
    /// Direct syntactic evidence (e.g., function call)
    Syntactic,
    /// Semantic evidence (e.g., similar naming patterns)
    Semantic,
    /// Type-based evidence (e.g., type compatibility)
    TypeBased,
    /// Import/include statements
    ImportBased,
    /// Documentation references
    DocumentationBased,
    /// Machine learning prediction
    MLPrediction,
    /// Transitive relationship evidence
    Transitive,
    /// Cross-language binding evidence
    CrossLanguage,
}

/// Relationship detection statistics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DetectionStats {
    /// Total relationships detected
    pub total_detected: usize,
    /// Relationships above confidence threshold
    pub high_confidence: usize,
    /// Relationships by type
    pub by_type: HashMap<EdgeType, usize>,
    /// Relationships by evidence type
    pub by_evidence: HashMap<EvidenceType, usize>,
    /// Average confidence score
    pub average_confidence: f64,
    /// Detection time in milliseconds
    pub detection_time_ms: u64,
}

/// Advanced relationship detection engine
pub struct RelationshipDetectionEngine {
    config: RelationshipConfig,
    detected_relationships: Arc<RwLock<Vec<DetectedRelationship>>>,
    node_cache: Arc<RwLock<HashMap<NodeId, Arc<dyn CodeNode>>>>,
    semantic_analyzer: SemanticAnalyzer,
    ml_predictor: Option<MLPredictor>,
}

/// Semantic analysis for relationship detection
struct SemanticAnalyzer {
    name_similarity_threshold: f64,
    type_compatibility_cache: HashMap<(String, String), f64>,
}

/// Machine learning predictor for relationships
struct MLPredictor {
    model_path: String,
    feature_extractor: FeatureExtractor,
}

/// Feature extraction for ML prediction
struct FeatureExtractor {
    vocabulary: HashMap<String, usize>,
    feature_cache: HashMap<(NodeId, NodeId), Vec<f64>>,
}

impl RelationshipDetectionEngine {
    /// Create a new relationship detection engine
    pub fn new(config: RelationshipConfig) -> Self {
        Self {
            config,
            detected_relationships: Arc::new(RwLock::new(Vec::new())),
            node_cache: Arc::new(RwLock::new(HashMap::new())),
            semantic_analyzer: SemanticAnalyzer::new(),
            ml_predictor: None,
        }
    }

    /// Detect relationships between nodes
    pub async fn detect_relationships(
        &self,
        nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let start_time = std::time::Instant::now();
        let mut relationships = Vec::new();

        // Update node cache
        {
            let mut cache = self.node_cache.write().await;
            for node in nodes {
                cache.insert(node.id(), node.clone());
            }
        }

        // Detect syntactic relationships
        let syntactic_rels = self.detect_syntactic_relationships(nodes).await?;
        relationships.extend(syntactic_rels);

        // Detect semantic relationships if enabled
        if self.config.enable_semantic_analysis {
            let semantic_rels = self.detect_semantic_relationships(nodes).await?;
            relationships.extend(semantic_rels);
        }

        // Detect type-based relationships
        let type_rels = self.detect_type_relationships(nodes).await?;
        relationships.extend(type_rels);

        // Detect import-based relationships
        let import_rels = self.detect_import_relationships(nodes).await?;
        relationships.extend(import_rels);

        // Detect transitive relationships
        let transitive_rels = self.detect_transitive_relationships(&relationships).await?;
        relationships.extend(transitive_rels);

        // Apply ML prediction if enabled
        if self.config.enable_ml_detection && self.ml_predictor.is_some() {
            let ml_rels = self.detect_ml_relationships(nodes).await?;
            relationships.extend(ml_rels);
        }

        // Filter by confidence threshold
        relationships.retain(|rel| rel.confidence >= self.config.min_confidence);

        // Deduplicate relationships
        relationships = self.deduplicate_relationships(relationships).await?;

        // Store detected relationships
        {
            let mut stored = self.detected_relationships.write().await;
            stored.extend(relationships.clone());
        }

        let detection_time = start_time.elapsed().as_millis() as u64;
        tracing::info!(
            "Detected {} relationships in {}ms",
            relationships.len(),
            detection_time
        );

        Ok(relationships)
    }

    /// Detect syntactic relationships (direct code references)
    async fn detect_syntactic_relationships(
        &self,
        nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        // Group nodes by type for efficient processing
        let mut functions = Vec::new();
        let mut classes = Vec::new();
        let mut variables = Vec::new();
        let mut imports = Vec::new();

        for node in nodes {
            match node.node_type() {
                NodeType::Function => functions.push(node),
                NodeType::Class => classes.push(node),
                NodeType::Variable => variables.push(node),
                NodeType::Import => imports.push(node),
                _ => {}
            }
        }

        // Detect function call relationships
        relationships.extend(self.detect_function_calls(&functions, nodes).await?);

        // Detect inheritance relationships
        relationships.extend(self.detect_inheritance(&classes).await?);

        // Detect variable usage relationships
        relationships.extend(self.detect_variable_usage(&variables, &functions).await?);

        // Detect import relationships
        relationships.extend(self.detect_import_usage(&imports, nodes).await?);

        // Detect containment relationships
        relationships.extend(self.detect_containment(nodes).await?);

        // Also analyze existing edges for additional syntactic evidence
        for source_node in nodes {
            for edge in source_node.edges(None) {
                let confidence = self.calculate_syntactic_confidence(source_node, edge).await?;

                if confidence >= self.config.min_confidence {
                    let evidence = vec![RelationshipEvidence {
                        evidence_type: EvidenceType::Syntactic,
                        description: format!("Direct {} relationship", edge.edge_type().to_string()),
                        confidence_contribution: confidence,
                        location: Some(source_node.location().clone()),
                        context: HashMap::new(),
                    }];

                    relationships.push(DetectedRelationship {
                        source: source_node.id(),
                        target: edge.target(),
                        edge_type: edge.edge_type().clone(),
                        confidence,
                        evidence,
                        metadata: edge.metadata().clone(),
                        location: Some(source_node.location().clone()),
                    });
                }
            }
        }

        Ok(relationships)
    }

    /// Detect semantic relationships (naming patterns, documentation)
    async fn detect_semantic_relationships(
        &self,
        nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        for (i, source_node) in nodes.iter().enumerate() {
            for target_node in nodes.iter().skip(i + 1) {
                if let Some(relationship) = self.semantic_analyzer
                    .analyze_relationship(source_node, target_node).await? {
                    relationships.push(relationship);
                }
            }
        }

        Ok(relationships)
    }

    /// Detect type-based relationships
    async fn detect_type_relationships(
        &self,
        nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        // Group nodes by type for efficient analysis
        let mut nodes_by_type: HashMap<NodeType, Vec<&Arc<dyn CodeNode>>> = HashMap::new();
        for node in nodes {
            nodes_by_type.entry(node.node_type().clone()).or_default().push(node);
        }

        // Detect inheritance relationships
        if let Some(classes) = nodes_by_type.get(&NodeType::Class) {
            for class in classes {
                let inheritance_rels = self.detect_inheritance_relationships(class, nodes).await?;
                relationships.extend(inheritance_rels);
            }
        }

        // Detect interface implementation relationships
        if let Some(interfaces) = nodes_by_type.get(&NodeType::Interface) {
            for interface in interfaces {
                let impl_rels = self.detect_implementation_relationships(interface, nodes).await?;
                relationships.extend(impl_rels);
            }
        }

        Ok(relationships)
    }

    /// Detect import-based relationships
    async fn detect_import_relationships(
        &self,
        nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        for node in nodes {
            // Analyze import statements in the node's metadata
            if let Some(imports) = node.metadata().custom.get("imports") {
                if let Ok(import_list) = serde_json::from_value::<Vec<String>>(imports.clone()) {
                    for import in import_list {
                        if let Some(target_node) = self.find_node_by_name(&import, nodes).await? {
                            let confidence = 0.8; // High confidence for explicit imports
                            
                            let evidence = vec![RelationshipEvidence {
                                evidence_type: EvidenceType::ImportBased,
                                description: format!("Import statement: {}", import),
                                confidence_contribution: confidence,
                                location: Some(node.location().clone()),
                                context: HashMap::new(),
                            }];

                            relationships.push(DetectedRelationship {
                                source: node.id(),
                                target: target_node.id(),
                                edge_type: EdgeType::DependsOn,
                                confidence,
                                evidence,
                                metadata: EdgeMetadata {
                                    weight: 1.0,
                                    confidence,
                                    context: Some(format!("Import: {}", import)),
                                    custom: HashMap::new(),
                                },
                                location: Some(node.location().clone()),
                            });
                        }
                    }
                }
            }
        }

        Ok(relationships)
    }

    /// Detect transitive relationships
    async fn detect_transitive_relationships(
        &self,
        existing_relationships: &[DetectedRelationship],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut transitive_relationships = Vec::new();

        // Build adjacency map for efficient traversal
        let mut adjacency: HashMap<NodeId, Vec<&DetectedRelationship>> = HashMap::new();
        for rel in existing_relationships {
            adjacency.entry(rel.source).or_default().push(rel);
        }

        // Detect transitive relationships up to max depth
        for rel in existing_relationships {
            let transitive = self.find_transitive_relationships(
                rel,
                &adjacency,
                1,
                &mut HashSet::new(),
            ).await?;
            transitive_relationships.extend(transitive);
        }

        Ok(transitive_relationships)
    }

    /// Detect ML-based relationships
    async fn detect_ml_relationships(
        &self,
        _nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        // Placeholder for ML-based relationship detection
        // This would integrate with a trained model to predict relationships
        Ok(Vec::new())
    }

    /// Calculate confidence for syntactic relationships
    async fn calculate_syntactic_confidence(
        &self,
        _source: &Arc<dyn CodeNode>,
        edge: &dyn CodeEdge,
    ) -> Result<ConfidenceScore> {
        // Base confidence from edge metadata
        let base_confidence = edge.metadata().confidence;
        
        // Apply relationship type weight
        let weight = self.config.relationship_weights
            .get(edge.edge_type())
            .copied()
            .unwrap_or(1.0);
        
        Ok((base_confidence * weight).min(1.0))
    }

    /// Find node by name
    async fn find_node_by_name(
        &self,
        name: &str,
        nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Option<Arc<dyn CodeNode>>> {
        for node in nodes {
            if node.name() == name {
                return Ok(Some(node.clone()));
            }
        }
        Ok(None)
    }

    /// Detect inheritance relationships
    async fn detect_inheritance_relationships(
        &self,
        _class: &Arc<dyn CodeNode>,
        _nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        // Placeholder for inheritance detection
        Ok(Vec::new())
    }

    /// Detect interface implementation relationships
    async fn detect_implementation_relationships(
        &self,
        _interface: &Arc<dyn CodeNode>,
        _nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        // Placeholder for implementation detection
        Ok(Vec::new())
    }

    /// Find transitive relationships iteratively
    async fn find_transitive_relationships(
        &self,
        base_rel: &DetectedRelationship,
        adjacency: &HashMap<NodeId, Vec<&DetectedRelationship>>,
        _depth: usize,
        _visited: &mut HashSet<NodeId>,
    ) -> Result<Vec<DetectedRelationship>> {
        let mut transitive_rels = Vec::new();
        let mut queue = vec![(base_rel, 1)]; // (relationship, depth)
        let mut visited = HashSet::new();

        while let Some((current_rel, depth)) = queue.pop() {
            if depth > self.config.max_transitive_depth || visited.contains(&current_rel.target) {
                continue;
            }

            visited.insert(current_rel.target);

            if let Some(next_rels) = adjacency.get(&current_rel.target) {
                for next_rel in next_rels {
                    // Calculate transitive confidence (decreases with depth)
                    let confidence_decay = 0.8_f64.powi(depth as i32);
                    let transitive_confidence = (base_rel.confidence * next_rel.confidence * confidence_decay).min(1.0);

                    if transitive_confidence >= self.config.min_confidence {
                        let evidence = vec![RelationshipEvidence {
                            evidence_type: EvidenceType::Transitive,
                            description: format!(
                                "Transitive relationship via {} (depth {})",
                                current_rel.target,
                                depth
                            ),
                            confidence_contribution: transitive_confidence,
                            location: base_rel.location.clone(),
                            context: HashMap::new(),
                        }];

                        transitive_rels.push(DetectedRelationship {
                            source: base_rel.source,
                            target: next_rel.target,
                            edge_type: next_rel.edge_type.clone(),
                            confidence: transitive_confidence,
                            evidence,
                            metadata: EdgeMetadata {
                                weight: transitive_confidence,
                                confidence: transitive_confidence,
                                context: Some(format!("Transitive via {}", current_rel.target)),
                                custom: HashMap::new(),
                            },
                            location: base_rel.location.clone(),
                        });

                        // Add to queue for further exploration
                        if depth < self.config.max_transitive_depth {
                            queue.push((next_rel, depth + 1));
                        }
                    }
                }
            }
        }

        Ok(transitive_rels)
    }

    /// Deduplicate relationships
    async fn deduplicate_relationships(
        &self,
        mut relationships: Vec<DetectedRelationship>,
    ) -> Result<Vec<DetectedRelationship>> {
        // Sort by confidence (highest first)
        relationships.sort_by(|a, b| b.confidence.partial_cmp(&a.confidence).unwrap());

        let mut seen = HashSet::new();
        let mut deduplicated = Vec::new();

        for rel in relationships {
            let key = (rel.source, rel.target, rel.edge_type.clone());
            if !seen.contains(&key) {
                seen.insert(key);
                deduplicated.push(rel);
            }
        }

        Ok(deduplicated)
    }

    /// Get detection statistics
    pub async fn get_detection_stats(&self) -> Result<DetectionStats> {
        let relationships = self.detected_relationships.read().await;
        
        let total_detected = relationships.len();
        let high_confidence = relationships.iter()
            .filter(|r| r.confidence >= 0.8)
            .count();

        let mut by_type = HashMap::new();
        let mut by_evidence = HashMap::new();
        let mut total_confidence = 0.0;

        for rel in relationships.iter() {
            *by_type.entry(rel.edge_type.clone()).or_insert(0) += 1;
            total_confidence += rel.confidence;

            for evidence in &rel.evidence {
                *by_evidence.entry(evidence.evidence_type.clone()).or_insert(0) += 1;
            }
        }

        let average_confidence = if total_detected > 0 {
            total_confidence / total_detected as f64
        } else {
            0.0
        };

        Ok(DetectionStats {
            total_detected,
            high_confidence,
            by_type,
            by_evidence,
            average_confidence,
            detection_time_ms: 0, // Would be set during actual detection
        })
    }

    /// Clear detected relationships
    pub async fn clear_relationships(&self) -> Result<()> {
        let mut relationships = self.detected_relationships.write().await;
        relationships.clear();
        Ok(())
    }
}

impl SemanticAnalyzer {
    fn new() -> Self {
        Self {
            name_similarity_threshold: 0.7,
            type_compatibility_cache: HashMap::new(),
        }
    }

    async fn analyze_relationship(
        &self,
        source: &Arc<dyn CodeNode>,
        target: &Arc<dyn CodeNode>,
    ) -> Result<Option<DetectedRelationship>> {
        // Calculate name similarity
        let name_similarity = self.calculate_name_similarity(source.name(), target.name());
        
        if name_similarity >= self.name_similarity_threshold {
            let confidence = name_similarity * 0.6; // Semantic relationships have moderate confidence
            
            let evidence = vec![RelationshipEvidence {
                evidence_type: EvidenceType::Semantic,
                description: format!(
                    "Similar names: {} <-> {} (similarity: {:.2})",
                    source.name(),
                    target.name(),
                    name_similarity
                ),
                confidence_contribution: confidence,
                location: Some(source.location().clone()),
                context: HashMap::new(),
            }];

            return Ok(Some(DetectedRelationship {
                source: source.id(),
                target: target.id(),
                edge_type: EdgeType::References, // Default to references for semantic relationships
                confidence,
                evidence,
                metadata: EdgeMetadata {
                    weight: confidence,
                    confidence,
                    context: Some("Semantic similarity".to_string()),
                    custom: HashMap::new(),
                },
                location: Some(source.location().clone()),
            }));
        }

        Ok(None)
    }

    fn calculate_name_similarity(&self, name1: &str, name2: &str) -> f64 {
        // Simple Levenshtein distance-based similarity
        let distance = levenshtein_distance(name1, name2);
        let max_len = name1.len().max(name2.len());
        
        if max_len == 0 {
            1.0
        } else {
            1.0 - (distance as f64 / max_len as f64)
        }
    }
}

/// Calculate Levenshtein distance between two strings
fn levenshtein_distance(s1: &str, s2: &str) -> usize {
    let len1 = s1.len();
    let len2 = s2.len();
    let mut matrix = vec![vec![0; len2 + 1]; len1 + 1];

    for i in 0..=len1 {
        matrix[i][0] = i;
    }
    for j in 0..=len2 {
        matrix[0][j] = j;
    }

    for (i, c1) in s1.chars().enumerate() {
        for (j, c2) in s2.chars().enumerate() {
            let cost = if c1 == c2 { 0 } else { 1 };
            matrix[i + 1][j + 1] = (matrix[i][j + 1] + 1)
                .min(matrix[i + 1][j] + 1)
                .min(matrix[i][j] + cost);
        }
    }

    matrix[len1][len2]
}

impl EdgeType {
    fn to_string(&self) -> &'static str {
        match self {
            EdgeType::Calls => "calls",
            EdgeType::References => "references",
            EdgeType::Inherits => "inherits",
            EdgeType::Implements => "implements",
            EdgeType::Contains => "contains",
            EdgeType::DependsOn => "depends_on",
            EdgeType::Imports => "imports",
            EdgeType::Defines => "defines",
            EdgeType::Uses => "uses",
            EdgeType::ControlFlow => "control_flow",
            EdgeType::DataFlow => "data_flow",
            EdgeType::TypeRelation => "type_relation",
            EdgeType::Unknown => "unknown",
        }
    }
}

impl RelationshipDetectionEngine {
    /// Detect function call relationships
    async fn detect_function_calls(
        &self,
        functions: &[&Arc<dyn CodeNode>],
        all_nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        for caller in functions {
            // Analyze function body for calls (simplified)
            let caller_location = caller.location();

            for callee in all_nodes {
                if caller.id() != callee.id() && matches!(callee.node_type(), NodeType::Function) {
                    // Check for function call patterns
                    let confidence = self.calculate_call_confidence(caller, callee).await;

                    if confidence >= self.config.min_confidence {
                        let evidence = RelationshipEvidence {
                            evidence_type: EvidenceType::Syntactic,
                            description: format!("Function {} calls {}", caller.name(), callee.name()),
                            confidence_contribution: confidence,
                            location: Some(caller_location.clone()),
                            context: self.build_call_context(caller, callee).await,
                        };

                        relationships.push(DetectedRelationship {
                            source: caller.id(),
                            target: callee.id(),
                            edge_type: EdgeType::Calls,
                            confidence,
                            evidence: vec![evidence],
                            metadata: EdgeMetadata::default(),
                            location: Some(caller_location.clone()),
                        });
                    }
                }
            }
        }

        Ok(relationships)
    }

    /// Detect inheritance relationships
    async fn detect_inheritance(
        &self,
        classes: &[&Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        for child_class in classes {
            // Check metadata for inheritance information
            let _metadata = child_class.metadata();

            // Look for inheritance patterns in class definition
            for parent_class in classes {
                if child_class.id() != parent_class.id() {
                    let confidence = self.calculate_inheritance_confidence(child_class, parent_class).await;

                    if confidence >= self.config.min_confidence {
                        let evidence = RelationshipEvidence {
                            evidence_type: EvidenceType::Syntactic,
                            description: format!("Class {} inherits from {}",
                                child_class.name(), parent_class.name()),
                            confidence_contribution: confidence,
                            location: Some(child_class.location().clone()),
                            context: HashMap::new(),
                        };

                        relationships.push(DetectedRelationship {
                            source: child_class.id(),
                            target: parent_class.id(),
                            edge_type: EdgeType::Inherits,
                            confidence,
                            evidence: vec![evidence],
                            metadata: EdgeMetadata::default(),
                            location: Some(child_class.location().clone()),
                        });
                    }
                }
            }
        }

        Ok(relationships)
    }

    /// Detect variable usage relationships
    async fn detect_variable_usage(
        &self,
        variables: &[&Arc<dyn CodeNode>],
        functions: &[&Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        for variable in variables {
            for function in functions {
                let confidence = self.calculate_variable_usage_confidence(variable, function).await;

                if confidence >= self.config.min_confidence {
                    let evidence = RelationshipEvidence {
                        evidence_type: EvidenceType::Syntactic,
                        description: format!("Function {} uses variable {}",
                            function.name(), variable.name()),
                        confidence_contribution: confidence,
                        location: Some(function.location().clone()),
                        context: HashMap::new(),
                    };

                    relationships.push(DetectedRelationship {
                        source: function.id(),
                        target: variable.id(),
                        edge_type: EdgeType::Uses,
                        confidence,
                        evidence: vec![evidence],
                        metadata: EdgeMetadata::default(),
                        location: Some(function.location().clone()),
                    });
                }
            }
        }

        Ok(relationships)
    }

    /// Detect import usage relationships
    async fn detect_import_usage(
        &self,
        imports: &[&Arc<dyn CodeNode>],
        all_nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        for import in imports {
            for node in all_nodes {
                if import.id() != node.id() {
                    let confidence = self.calculate_import_usage_confidence(import, node).await;

                    if confidence >= self.config.min_confidence {
                        let evidence = RelationshipEvidence {
                            evidence_type: EvidenceType::ImportBased,
                            description: format!("Node {} uses import {}",
                                node.name(), import.name()),
                            confidence_contribution: confidence,
                            location: Some(node.location().clone()),
                            context: HashMap::new(),
                        };

                        relationships.push(DetectedRelationship {
                            source: node.id(),
                            target: import.id(),
                            edge_type: EdgeType::DependsOn,
                            confidence,
                            evidence: vec![evidence],
                            metadata: EdgeMetadata::default(),
                            location: Some(node.location().clone()),
                        });
                    }
                }
            }
        }

        Ok(relationships)
    }

    /// Detect containment relationships
    async fn detect_containment(
        &self,
        nodes: &[Arc<dyn CodeNode>],
    ) -> Result<Vec<DetectedRelationship>> {
        let mut relationships = Vec::new();

        // Group nodes by file/location for containment analysis
        let mut location_groups: HashMap<String, Vec<&Arc<dyn CodeNode>>> = HashMap::new();

        for node in nodes {
            let file_path = node.location().file_path.clone();
            location_groups.entry(file_path).or_insert_with(Vec::new).push(node);
        }

        // Detect containment within each file
        for (_file_path, file_nodes) in location_groups {
            for container in &file_nodes {
                for contained in &file_nodes {
                    if container.id() != contained.id() {
                        let confidence = self.calculate_containment_confidence(container, contained).await;

                        if confidence >= self.config.min_confidence {
                            let evidence = RelationshipEvidence {
                                evidence_type: EvidenceType::Syntactic,
                                description: format!("{} contains {}",
                                    container.name(), contained.name()),
                                confidence_contribution: confidence,
                                location: Some(container.location().clone()),
                                context: HashMap::new(),
                            };

                            relationships.push(DetectedRelationship {
                                source: container.id(),
                                target: contained.id(),
                                edge_type: EdgeType::Contains,
                                confidence,
                                evidence: vec![evidence],
                                metadata: EdgeMetadata::default(),
                                location: Some(container.location().clone()),
                            });
                        }
                    }
                }
            }
        }

        Ok(relationships)
    }

    /// Calculate confidence for function call relationships
    async fn calculate_call_confidence(
        &self,
        caller: &Arc<dyn CodeNode>,
        callee: &Arc<dyn CodeNode>,
    ) -> f64 {
        let mut confidence: f64 = 0.0;

        // Check if callee name appears in caller's context
        if caller.name().contains(callee.name()) {
            confidence += 0.6;
        }

        // Check for common naming patterns
        if self.has_call_naming_pattern(caller.name(), callee.name()) {
            confidence += 0.3;
        }

        // Check location proximity (same file gets higher confidence)
        if caller.location().file_path == callee.location().file_path {
            confidence += 0.1;
        }

        confidence.min(1.0)
    }

    /// Calculate confidence for inheritance relationships
    async fn calculate_inheritance_confidence(
        &self,
        child: &Arc<dyn CodeNode>,
        parent: &Arc<dyn CodeNode>,
    ) -> f64 {
        let mut confidence: f64 = 0.0;

        // Check for inheritance keywords or patterns
        if self.has_inheritance_pattern(child.name(), parent.name()) {
            confidence += 0.8;
        }

        // Check naming conventions (e.g., BaseClass -> DerivedClass)
        if self.has_inheritance_naming_pattern(child.name(), parent.name()) {
            confidence += 0.2;
        }

        confidence.min(1.0)
    }

    /// Calculate confidence for variable usage relationships
    async fn calculate_variable_usage_confidence(
        &self,
        variable: &Arc<dyn CodeNode>,
        function: &Arc<dyn CodeNode>,
    ) -> f64 {
        let mut confidence: f64 = 0.0;

        // Check if variable name appears in function context
        if function.name().contains(variable.name()) {
            confidence += 0.7;
        }

        // Check location proximity
        if variable.location().file_path == function.location().file_path {
            confidence += 0.2;
        }

        // Check scope relationships
        if self.is_in_scope(variable, function) {
            confidence += 0.1;
        }

        confidence.min(1.0)
    }

    /// Calculate confidence for import usage relationships
    async fn calculate_import_usage_confidence(
        &self,
        import: &Arc<dyn CodeNode>,
        node: &Arc<dyn CodeNode>,
    ) -> f64 {
        let mut confidence: f64 = 0.0;

        // Extract module name from import
        let import_name = self.extract_module_name(import.name());

        // Check if imported module is referenced
        if node.name().contains(&import_name) {
            confidence += 0.8;
        }

        // Check if in same file (imports affect same-file nodes)
        if import.location().file_path == node.location().file_path {
            confidence += 0.2;
        }

        confidence.min(1.0)
    }

    /// Calculate confidence for containment relationships
    async fn calculate_containment_confidence(
        &self,
        container: &Arc<dyn CodeNode>,
        contained: &Arc<dyn CodeNode>,
    ) -> f64 {
        let mut confidence: f64 = 0.0;

        // Check location hierarchy (line numbers)
        let container_loc = container.location();
        let contained_loc = contained.location();

        if container_loc.file_path == contained_loc.file_path {
            // Check if contained is within container's boundaries
            if container_loc.start_line <= contained_loc.start_line &&
               container_loc.end_line >= contained_loc.end_line {
                confidence += 0.9;
            }
        }

        // Check node type hierarchy (class contains method, etc.)
        confidence += self.calculate_type_containment_confidence(container, contained);

        confidence.min(1.0)
    }

    /// Build context information for function calls
    async fn build_call_context(
        &self,
        caller: &Arc<dyn CodeNode>,
        callee: &Arc<dyn CodeNode>,
    ) -> HashMap<String, String> {
        let mut context = HashMap::new();

        context.insert("caller_type".to_string(), format!("{:?}", caller.node_type()));
        context.insert("callee_type".to_string(), format!("{:?}", callee.node_type()));
        context.insert("same_file".to_string(),
            (caller.location().file_path == callee.location().file_path).to_string());
        context.insert("caller_language".to_string(), caller.language().to_string());
        context.insert("callee_language".to_string(), callee.language().to_string());

        context
    }

    /// Check for call naming patterns
    fn has_call_naming_pattern(&self, caller_name: &str, callee_name: &str) -> bool {
        // Simple pattern matching - could be enhanced with more sophisticated analysis
        caller_name.to_lowercase().contains(&callee_name.to_lowercase()) ||
        callee_name.to_lowercase().contains(&caller_name.to_lowercase())
    }

    /// Check for inheritance patterns
    fn has_inheritance_pattern(&self, child_name: &str, parent_name: &str) -> bool {
        // Look for common inheritance patterns
        child_name.contains("extends") && child_name.contains(parent_name) ||
        child_name.contains("inherits") && child_name.contains(parent_name) ||
        child_name.ends_with("Impl") && parent_name.ends_with("Interface")
    }

    /// Check for inheritance naming patterns
    fn has_inheritance_naming_pattern(&self, child_name: &str, parent_name: &str) -> bool {
        // Common naming patterns for inheritance
        (parent_name.starts_with("Base") && child_name.contains(&parent_name[4..])) ||
        (parent_name.starts_with("Abstract") && child_name.contains(&parent_name[8..])) ||
        (child_name.starts_with(parent_name) && child_name.len() > parent_name.len())
    }

    /// Check if variable is in scope of function
    fn is_in_scope(&self, variable: &Arc<dyn CodeNode>, function: &Arc<dyn CodeNode>) -> bool {
        // Simplified scope checking - could be enhanced with proper scope analysis
        let var_loc = variable.location();
        let func_loc = function.location();

        var_loc.file_path == func_loc.file_path &&
        var_loc.start_line >= func_loc.start_line &&
        var_loc.end_line <= func_loc.end_line
    }

    /// Extract module name from import statement
    fn extract_module_name(&self, import_name: &str) -> String {
        // Handle different import formats
        if import_name.starts_with("from ") {
            // "from module import ..." -> "module"
            import_name.split_whitespace().nth(1).unwrap_or(import_name).to_string()
        } else if import_name.contains(" as ") {
            // "import module as alias" -> "module"
            import_name.split(" as ").next().unwrap_or(import_name).trim().to_string()
        } else {
            // "import module" -> "module"
            import_name.replace("import ", "").trim().to_string()
        }
    }

    /// Calculate type-based containment confidence
    fn calculate_type_containment_confidence(
        &self,
        container: &Arc<dyn CodeNode>,
        contained: &Arc<dyn CodeNode>,
    ) -> f64 {
        match (container.node_type(), contained.node_type()) {
            (NodeType::Class, NodeType::Function) => 0.8,  // Class contains method
            (NodeType::Class, NodeType::Variable) => 0.7,  // Class contains field
            (NodeType::Function, NodeType::Variable) => 0.6, // Function contains local var
            (NodeType::Module, _) => 0.5,                   // Module contains anything
            _ => 0.0,
        }
    }
}
